package serial;

import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;

public class CmdSender extends Thread {
	private String[] command;
	private String result, filename;
	private boolean complete, isQuitter;
	private ArrayList<SerialReaderListener> listeners;
	
	private CmdSender(String cmdFile, boolean quit, ArrayList<SerialReaderListener> listeners) {
		filename = cmdFile;
		isQuitter = quit;
		complete = false;
		this.listeners = new ArrayList<SerialReaderListener>();
		for (SerialReaderListener srl: listeners) {
			this.listeners.add(srl);
		}
		
	}

	public CmdSender(String port, String cmd, boolean quit, ArrayList<SerialReaderListener> listeners) throws IOException {
		this(CMD_FILE, quit, listeners);
		cmdToFile(cmd);
		command = makeCmd(port, isQuitter);
	}
	
	public CmdSender(String port, boolean quit, String cmdFile, ArrayList<SerialReaderListener> listeners) {
		this(cmdFile, quit, listeners);
		command = makeCmd(port, quit, filename);
	}
	
	private final static String CMD_FILE = "cmd.tmp";
	
	public final static String CMD = "./fileToNxt.exe";
	
	public static void cmdToFile(String cmd) throws IOException {
		File f = new File(CMD_FILE);
		PrintWriter ps = new PrintWriter(new FileWriter(f));
		ps.print("collectgarbage(\"setpause\", 50)\n");
		ps.print(cmd);
		ps.close();
	}
	
	public static String[] makeCmd(String port, boolean quit, String filename) {
		return quit ? new String[]{CMD, port, filename, "-quit"} : new String[]{CMD, port, filename};
	}
	
	public static String[] makeCmd(String port, boolean quit) {
		return makeCmd(port, quit, CMD_FILE);
	}
	
	/*
	public static boolean responsePresentIn(String output, String response) {
		int first = output.indexOf(response);
		int second = output.indexOf(response, first + response.length());
		return second != -1;
	}
	*/
	
	public static String echoesStripped(String output) {
		String result = "";
		for (String line: output.split("\\n")) {
			if (line.charAt(0) != '>') {
				result += line + "\n";
			}
		}
		return result;
	}
	
	public static boolean responsePresentIn(String output, String response) {
		return echoesStripped(output).contains(response);
	}
	
	public static String processOutput(Process p) throws IOException, InterruptedException {
		String result = "";
		Scanner s = new Scanner(p.getInputStream().available() > 0 ? p.getInputStream() : p.getErrorStream());
		while (s.hasNextLine()) {
			result += s.nextLine() + '\n';
		}
		p.waitFor();
		return result;
	}
	/*
	public static String purgeEchoes(String s) {
		Scanner scan = new Scanner(s);
		String result = "";
		while (scan.hasNextLine()) {
			String line = scan.nextLine();
			if (!line.startsWith(">")) {
				result += line + '\n';
			}
		}
		return result;
	}
	*/
	public boolean isCompleted() {
		return complete;
	}

	public void halt() {
		complete = true;
	}

	public void run() {
		try {
			result = "";
			Process p = Runtime.getRuntime().exec(command);
			if (!isQuitter) {
				while (p.getInputStream().available() == 0 && p.getErrorStream().available() == 0 && !complete) {}

				if (complete) {
					p.destroy();
				} else {
					result = processOutput(p);
				}
			}
			for (SerialReaderListener srl: listeners) {
				srl.halted();
				srl.stringReceived(result);
			}
		} catch (IOException ioe) {
			ioe.printStackTrace();
		} catch (InterruptedException ie) {
			ie.printStackTrace();
		}
		complete = true;
	}

	public String getResult() {
		return result;
	}

	public static void main(String[] args) throws IOException {
		if (args.length < 2) {
			System.out.println("Usage: CmdSender port commandFile [-quit]");
			System.exit(1);
		}
		File f = new File(args[1]);
		Scanner s = new Scanner(f);
		String cmd = "";
		while (s.hasNextLine()) {
			cmd += s.nextLine() + '\n';
		}
		CmdSender r1 = new CmdSender(args[0], cmd, args.length == 3, new ArrayList<SerialReaderListener>());
		r1.start();
		while (!r1.isCompleted()) {}
		System.out.print(r1.getResult());
	}
}
